#pragma once

#include "CInterlockedReferenceCount.h"
#include "IntrusiveList.h"
#include "HWTextureAtlas.h"

class HWTexture;

class CLinearGradientBrush;
class CLinearGradientBrushSpan;
class CRenderTarget;



class HWTextureManager :
	public CInterlockedReferenceCount
{

public: 
	static HRESULT Create(CRenderTarget * pRenderTarget, HWTextureManager * * ppHWTextureManager);
	HRESULT CreateTexture(struct IPALSurface * pTextureSource, HWTexture * * ppTexture);
	HRESULT CreateTexture(enum PixelFormat pixelFormat, XUINT32 width, XUINT32 height, enum HWTextureFlags flags, HWTexture * * ppTexture);
	HRESULT CreateTextureForHardware(XUINT32 widthWithPadding, XUINT32 heightWithPadding, HWTexture * * ppTexture);
	HRESULT CreateGradientTexture(const CLinearGradientBrush * pBrush, CLinearGradientBrushSpan * pGradientBrushSpan, HWTexture * * ppHWTexture);
	HRESULT CreateStandAloneTexture(const struct XSIZE * pAtlasSize, const struct XRECT_WH * pViewBounds, XBOOL includePadding, XBOOL isOpaque, HWTexture * * ppTexture);
	static XUINT32 FitsEfficientlyInMaxAtlas(const struct XSIZE * pTextureSize);
	XUINT32 GetMaxStandaloneTextureSize();
	HRESULT TrimMemory(XBOOL freeVSISAtlases );
	HRESULT GetSurfaces(xvector<xref_ptr<IPALSurface> > * pSurfaceList);
	void AddAtlasToList(struct IntrusiveList<HWTextureAtlas>::ListEntry * pListEntry);
	void RemoveAtlasFromList(struct IntrusiveList<HWTextureAtlas>::ListEntry * pListEntry);
	void MarkAllAtlasesAsLost();
	HRESULT OfferAtlases(struct IPALOptimizedGraphicsDevice * pDevice);
	HRESULT ReclaimAtlases(struct IPALOptimizedGraphicsDevice * pDevice, XBOOL * pWasAnySurfaceDiscarded);
	void UpdateAtlasSqmData(CCoreServices *);
private: 
	HWTextureManager(CRenderTarget * pRenderTarget);
	virtual ~HWTextureManager();
	HRESULT RemoveLostAtlasesFromPool(xvector<HWTextureAtlas *> * pPool);
	HRESULT CleanupAtlasPool(xvector<HWTextureAtlas *> * pAtlases, XUINT32 * pCurrentIndex, XBOOL freeEmptyAtlases);
	void ClearAtlasPools();
public: 
	static const XUINT32 MaxGradientTextureSize;

private: 
	CRenderTarget * m_pRenderTargetNoRef;

	struct
	{
	public: 
		xvector<HWTextureAtlas *> atlases; 
		XUINT32 currentIndex;
		XUINT32 createNextAtlasMinimalSize;

	} m_atlasPools[3];

	static const XUINT32 sc_grayAtlasPool;
	static const XUINT32 sc_colorAtlasPool;
	static const XUINT32 sc_colorTileAtlasPool;
	IntrusiveList<HWTextureAtlas> m_atlases;
};